package com.lipaluma.excel.config;

import com.lipaluma.excel.annotations.config.Excel;
import com.lipaluma.config.Configuration;
import com.lipaluma.exceptions.CsvParserException;
import com.lipaluma.io.SourceFactory;
import com.lipaluma.excel.io.ExcelSourceFactory;
import com.lipaluma.excel.xml.configuration.XmlExcelConfiguration;

public class ExcelConfiguration implements Configuration {
	private int nbLinesHeader = 1;
	private int headerLine = 1;
	private boolean mapColumnsByHeaders = false;
	private boolean hasHeader = false;
	private boolean writeHeader = false;
	private String sheetName;
	private Integer sheetIndex;
	private ExcelExtension extension;

	public ExcelConfiguration(ExcelExtension extension) {
		this.extension = extension;
		mapColumnsByHeaders = false;
		nbLinesHeader = 1;
		headerLine = 1;
		hasHeader = false;
		writeHeader = false;
		sheetIndex = 0;
	}
	
	public ExcelConfiguration(Excel excel) {
		mapColumnsByHeaders = excel.mapColumnsByHeaders();
		nbLinesHeader = excel.nbLinesHeader();
		headerLine = excel.headerLine();
		hasHeader = excel.hasHeader();
		writeHeader = excel.writeHeader();
		if(excel.sheetIndex() != -1)
			sheetIndex = excel.sheetIndex();
		sheetName = excel.sheetName();
		extension = excel.extension();
	}

	public ExcelConfiguration(XmlExcelConfiguration configuration) {
		mapColumnsByHeaders = configuration.mapColumnsByHeaders();
		nbLinesHeader = configuration.getNbLinesHeader();
		headerLine = configuration.getHeaderLine();
		hasHeader = configuration.hasHeader();
		writeHeader = configuration.writeHeader();
		sheetIndex = configuration.getSheetIndex();
		sheetName = configuration.getSheetName();
		extension = configuration.getExtension();
	}

	private ExcelConfiguration(Builder builder) {
		mapColumnsByHeaders = builder.mapColumnsByHeaders;
		nbLinesHeader = builder.nbLinesHeader;
		headerLine = builder.headerLine;
		hasHeader = builder.hasHeader;
		writeHeader = builder.writeHeader;
		sheetIndex = builder.sheetIndex;
		sheetName = builder.sheetName;
		extension = builder.extension;
	}

	@Override
	public SourceFactory createSourceFactory() {
		if(sheetIndex != null)
			return new ExcelSourceFactory(extension, sheetIndex);
		else if(sheetName != null)
			return new ExcelSourceFactory(extension, sheetName);
		else
			throw new CsvParserException("Error on creation of the Excel source : the sheet index or name must be defined");
	}
	
	public int getHeaderLine() {
		return headerLine;
	}
	
	public boolean isColumnsMappedByHeaders() {
		return mapColumnsByHeaders;
	}
	
	public int getLinesHeaderNumber() {
		return nbLinesHeader;
	}
	
	public boolean hasHeader() {
		return hasHeader;
	}

	public boolean writeHeader() {
		return writeHeader;
	}
	
	public Integer getSheetIndex() {
		return sheetIndex;
	}
	
	public String getSheetName() {
		return sheetName;
	}
	
	public ExcelExtension getExtension() {
		return extension;
	}
	
	public static Builder builder(ExcelExtension extension) {
		return new Builder(extension);
	}


	public static class Builder {
		private int nbLinesHeader = 1;
		private int headerLine = 1;
		private boolean mapColumnsByHeaders = false;
		private boolean hasHeader = false;
		private boolean writeHeader = false;
		private String sheetName;
		private Integer sheetIndex;
		public ExcelExtension extension;

		public Builder(ExcelExtension extension) {
			this.extension = extension;
		}
		public Builder withHeadersNameLineAt(int headerLine) {
			this.headerLine = headerLine;
			return this;
		}
		public Builder hasHeader() {
			this.hasHeader = true;
			return this;
		}
		public Builder writeHeader() {
			this.writeHeader = true;
			return this;
		}
		public Builder withNumberLinesOfHeader(int nbLines) {
			this.nbLinesHeader = nbLines;
			return this;
		}
		public Builder mapColumnsByHeadersName() {
			this.mapColumnsByHeaders = true;
			return this;
		}
		public Builder onSheetIndex(int index){
			this.sheetIndex = index;
			return this;
		}
		public Builder onSheetName(String name){
			this.sheetName = name;
			return this;
		}
		public ExcelConfiguration build(){
			return new ExcelConfiguration(this);
		}
	}
}
